/*
ubertk is a flexible GUI toolkit targetted towards graphics applications.
Copyright (C) 2007 - 2013 John Tsiombikas <nuclear@member.fsf.org>,
                          Michael Georgoulopoulos <mgeorgoulopoulos@gmail.com>,
				          Kostas Michalopoulos <badsector@slashstone.com>

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
   list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
   derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/

#ifndef UTK_EVENTS_H_
#define UTK_EVENTS_H_

#include <list>
#include <utk_types.h>

namespace utk {

class Widget;

enum {
	MOUSE_LEFT,
	MOUSE_MIDDLE,
	MOUSE_RIGHT,
	MOUSE_AUX1,
	MOUSE_AUX2
};
#define UTK_MOUSE_NONE		(-1)

// these correspond to X11 keysyms
enum {
	KEY_ESCAPE		= 27,
	KEY_DELETE		= 127,
	KEY_UP			= 273,
	KEY_DOWN		= 274,
	KEY_RIGHT		= 275,
	KEY_LEFT		= 276,
	KEY_INSERT		= 277,
	KEY_HOME		= 278,
	KEY_END			= 279,
	KEY_PAGEUP		= 280,
	KEY_PAGEDOWN	= 281
};

enum {
	EVENT_NULL = 0,
	EVENT_MMOTION,
	EVENT_MBUTTON,
	EVENT_MHOVER,
	EVENT_KEYBOARD,

	EVENT_CLICK = 100,
	EVENT_FOCUS,
	EVENT_MODIFY,
	EVENT_NOTIFY,

	EVENT_COUNT		// not an event :)
};

class Event {
protected:
	int event_id;

public:
	Widget *widget;

	Event();
	virtual ~Event();

	virtual int get_event_id() const;
};

// ---- low level events, generated by the app ----
class MouseEvent : public Event {
public:
	int x, y;

	MouseEvent(int x = 0, int y = 0);
};

class MMotionEvent : public MouseEvent {
public:
	MMotionEvent(int x = 0, int y = 0);
};

class MButtonEvent : public MouseEvent {
public:
	int button;
	bool pressed;
	int press_x, press_y;	// for depress events, the press coordinates

	MButtonEvent(int bn = 0, int x = 0, int y = 0);
};

class MHoverEvent : public MouseEvent {
public:
	bool enter;
	// for enter, this is the widget that lost the mouse.
	// for leave, this is the widget that got the mouse.
	Widget *other;

	MHoverEvent(bool enter, Widget *other, int x = 0, int y = 0);
};


class KeyboardEvent : public Event {
public:
	int key;
	bool pressed;

	KeyboardEvent(int key = 0);
};


// ---- high-level events, generated by UTK ----
class ClickEvent : public MouseEvent {
public:
	int button;
	unsigned int time;		// to catch double-clicks

	ClickEvent();
	virtual ~ClickEvent();
};

class FocusEvent : public Event {
public:
	bool focus;

	FocusEvent();
	virtual ~FocusEvent();
};

/* This is part of the low-level interface to utk.
 * The client program must call this to give input to utk.
 */
void event(Event *e);

enum { FOCUS_POINT, FOCUS_CLICK };

void set_focus_mode(unsigned int fmode);
unsigned int get_focus_mode();

int get_button_state();
Widget *get_button_press_widget();
IVec2 get_mouse_pos();
IVec2 get_last_drag_pos();
void grab_mouse(Widget *e);

void grab_focus(Widget *w);
void grab_win_focus(Widget *w);

void invalidate_widget(Widget *w);

void modalize_window(class Window *w);
void close_last_modal_window();

typedef void (*Callback)(Event*, void*);

struct CallbackClosure {
	Callback func;
	void *data;
};


extern std::list<Widget*> destruct_queue;

}	// end namespace utk

#endif	// UTK_EVENTS_H_
